using Pgvector;

namespace RAG.Infrastructure.Services;

/// <summary>
/// 向量距离计算服务 - 专门处理HNSW和余弦距离计算
/// </summary>
public class VectorDistanceService
{
    /// <summary>
    /// 标准化向量到单位长度
    /// </summary>
    public static float[] NormalizeVector(float[] vector)
    {
        var magnitude = CalculateMagnitude(vector);
        if (magnitude == 0.0f)
        {
            throw new ArgumentException("Cannot normalize zero vector");
        }

        var normalized = new float[vector.Length];
        for (int i = 0; i < vector.Length; i++)
        {
            normalized[i] = vector[i] / magnitude;
        }

        return normalized;
    }

    /// <summary>
    /// 计算向量的模长（L2范数）
    /// </summary>
    public static float CalculateMagnitude(float[] vector)
    {
        double sum = 0.0;
        for (int i = 0; i < vector.Length; i++)
        {
            sum += vector[i] * vector[i];
        }
        return (float)Math.Sqrt(sum);
    }

    /// <summary>
    /// 计算余弦相似度 (范围: [-1, 1])
    /// 1 = 完全相同, 0 = 正交, -1 = 完全相反
    /// </summary>
    public static double CalculateCosineSimilarity(float[] vector1, float[] vector2)
    {
        if (vector1.Length != vector2.Length)
        {
            throw new ArgumentException($"Vector dimensions must match: {vector1.Length} vs {vector2.Length}");
        }

        double dotProduct = 0.0;
        double magnitude1 = 0.0;
        double magnitude2 = 0.0;

        for (int i = 0; i < vector1.Length; i++)
        {
            dotProduct += vector1[i] * vector2[i];
            magnitude1 += vector1[i] * vector1[i];
            magnitude2 += vector2[i] * vector2[i];
        }

        magnitude1 = Math.Sqrt(magnitude1);
        magnitude2 = Math.Sqrt(magnitude2);

        // 防止除零错误
        if (magnitude1 == 0.0 || magnitude2 == 0.0)
        {
            return 0.0; // 零向量与任何向量的相似度为0
        }

        double similarity = dotProduct / (magnitude1 * magnitude2);

        // 确保相似度在有效范围内（处理数值精度问题）
        return Math.Max(-1.0, Math.Min(1.0, similarity));
    }

    /// <summary>
    /// 计算余弦距离 (范围: [0, 2])
    /// 与pgvector的<=>操作符一致
    /// 0 = 完全相同, 1 = 正交, 2 = 完全相反
    /// </summary>
    public static double CalculateCosineDistance(float[] vector1, float[] vector2)
    {
        var similarity = CalculateCosineSimilarity(vector1, vector2);
        return 1.0 - similarity;
    }

    /// <summary>
    /// 将相似度转换为距离
    /// </summary>
    public static double SimilarityToDistance(double similarity)
    {
        return 1.0 - similarity;
    }

    /// <summary>
    /// 将距离转换为相似度
    /// </summary>
    public static double DistanceToSimilarity(double distance)
    {
        return 1.0 - distance;
    }

    /// <summary>
    /// 创建用于pgvector查询的Vector对象
    /// 确保向量格式正确
    /// </summary>
    public static Vector CreatePgVector(float[] vector)
    {
        if (vector == null || vector.Length == 0)
        {
            throw new ArgumentException("Vector cannot be null or empty");
        }

        // 检查向量中是否有无效值
        for (int i = 0; i < vector.Length; i++)
        {
            if (float.IsNaN(vector[i]) || float.IsInfinity(vector[i]))
            {
                throw new ArgumentException($"Vector contains invalid value at index {i}: {vector[i]}");
            }
        }

        return new Vector(vector);
    }

    /// <summary>
    /// 验证向量是否有效
    /// </summary>
    public static bool IsValidVector(float[] vector)
    {
        if (vector == null || vector.Length == 0)
        {
            return false;
        }

        for (int i = 0; i < vector.Length; i++)
        {
            if (float.IsNaN(vector[i]) || float.IsInfinity(vector[i]))
            {
                return false;
            }
        }

        return true;
    }

    /// <summary>
    /// 检查向量是否已标准化（模长接近1）
    /// </summary>
    public static bool IsNormalized(float[] vector, float tolerance = 1e-6f)
    {
        var magnitude = CalculateMagnitude(vector);
        return Math.Abs(magnitude - 1.0f) < tolerance;
    }

    /// <summary>
    /// 获取向量统计信息（用于调试）
    /// </summary>
    public static VectorStats GetVectorStats(float[] vector)
    {
        if (vector == null || vector.Length == 0)
        {
            return new VectorStats();
        }

        var magnitude = CalculateMagnitude(vector);
        var min = vector.Min();
        var max = vector.Max();
        var mean = vector.Average();
        var isNormalized = IsNormalized(vector);

        return new VectorStats
        {
            Dimension = vector.Length,
            Magnitude = magnitude,
            Min = min,
            Max = max,
            Mean = (float)mean,
            IsNormalized = isNormalized,
            Preview = vector.Take(5).ToArray()
        };
    }
}

/// <summary>
/// 向量统计信息
/// </summary>
public class VectorStats
{
    public int Dimension { get; set; }
    public float Magnitude { get; set; }
    public float Min { get; set; }
    public float Max { get; set; }
    public float Mean { get; set; }
    public bool IsNormalized { get; set; }
    public float[] Preview { get; set; } = Array.Empty<float>();

    public override string ToString()
    {
        return $"Dim:{Dimension}, Mag:{Magnitude:F4}, Range:[{Min:F4},{Max:F4}], Mean:{Mean:F4}, Norm:{IsNormalized}, Preview:[{string.Join(",", Preview.Select(v => v.ToString("F4")))}]";
    }
}
